/*
 * Copyright (C) 2011 Mette Bank, Rikke Jensen, Kenneth Brodersen, Thomas Pedersen
 * 
 * This file is part of digiPECS.
 * 
 * digiPECS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * digiPECS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with digiPECS.  If not, see <http://www.gnu.org/licenses/>.
 */

package sw6.digipecs.model;

import java.io.File;

import sw6.digipecs.R;
import sw6.digipecs.database.DBAdapter;
import sw6.digipecs.database.PictureCursor;
import sw6.digipecs.exceptions.DatabaseException;
import sw6.digipecs.exceptions.IDNotFoundException;
import sw6.digipecs.exceptions.ImageIsEmptyException;
import sw6.digipecs.exceptions.SoundNotFoundException;
import android.content.Context;
import android.net.Uri;
import android.widget.ImageView;

/**
 * This class describes, what is called an extended image in digiPECS. An
 * instance of this class contains a reference to an image resource and other
 * pecs specific information like a corresponding text to the picture or path to sound file. 
 * @author sw6.digipecs
 */
public class ExtImage {
	
	private boolean mEmpty = true;
	private String mText; 
	private String mUri;
	private String mSound;
	private int mId;
	protected DBAdapter mDB;
	
	/**
	 * Create a new ExtImage.
	 * 
	 * This function inserts a new entry in the database, containing the
	 * information about the picture. The newly created entry is then fetched
	 * from the database and returned.
	 * 
	 * @param  context            The context in which we run.
	 * @param  uri                Uri of the image file to be created.
	 * @param  text               Textual description of the image.
	 * @param	sound			   PAth to the image file to be created.
	 * @throws DatabaseException  If the image cannot be fetched from the
	 *                            database, after the entry has been created.
	 * @return The newly create ExtImage
	 */
	public static ExtImage CreateNew(Context context, String uri, String text, String sound) throws DatabaseException {
		ExtImage image;
		int id;
		
		DBAdapter adapter = new DBAdapter(context); 
		adapter.open(); 
		id = (int) adapter.addPicture(text, uri, sound); 
		adapter.close();
		
		try {
			image = new ExtImage(context, id);
		} catch (IDNotFoundException e) {
			throw new DatabaseException();
		}
		
		return image;
	}
	
	/**
	 * Constructor for an extended image.
	 * 
	 * This construct creates an empty picture, used for placeholders, e.g. in
	 * the sentence board when it is empty.
	 * 
	 * @param  context            The context in which we run.
	 */
	public ExtImage(Context context) {
		mEmpty = true;
		mDB = new DBAdapter(context);
	}
	
	/**
	 * Constructor for an extended image.
	 * 
	 * This construct fetches the image data from the database, accordingly to
	 * the given id number.  
	 * 
	 * @param  context              The context in which we run.
	 * @param  id                   ID of the image to fetch.
	 * @throws IDNotFoundException  If the ID could not be found in the
	 *                              database.
	 */
	public ExtImage(Context context, int id) throws IDNotFoundException
	{
		PictureCursor cursor;

		mDB = new DBAdapter(context);
		
		// Open the database adapter and get the picture
		mDB.open();
		cursor = mDB.fetchPicture(id);
		
		// If we got a picture get the data, else throw an exception
		if (cursor.moveToFirst()) {
			mEmpty = false;
			mUri = cursor.getPicturePath();
			mText = cursor.getPictureText();
			mSound = cursor.getSoundPath();
			mId = id;
		} else {
			mEmpty = true;
			
			cursor.close();
			mDB.close();
			throw new IDNotFoundException();
		}
		
		// Close the database again
		cursor.close();
		mDB.close();
	}
	
	/**
	 * Get the text describing the content of the picture.
	 *  
	 * @return String with text. 
	 * @throws ImageIsEmptyException If the image is empty.
	 */
	public String getText() throws ImageIsEmptyException {
		if (isEmpty()) {
			throw new ImageIsEmptyException();
		}
		
		return mText;
	}
	
	/**
	 * Get the id describing the picture.
	 *  
	 * @return int with ID. 
	 * @throws ImageIsEmptyException If the image is empty.
	 */
	public int getId() throws ImageIsEmptyException {
		if (isEmpty()) {
			throw new ImageIsEmptyException();
		}
		
		return mId;
	}
	
	/**
	 * Get the uri describing the location of the image file.
	 * 
	 * \remark This is only for storing images in a database. For creating
	 * views, see setImage().
	 *  
	 * @return uri is String format.
	 * @throws ImageIsEmptyException If the image is empty.
	 */
	public String getUri() throws ImageIsEmptyException {
		if (isEmpty()) {
			throw new ImageIsEmptyException();
		}
		
		return mUri;
	}
	
	/**
	 *  Get the sound path describing the location of the sound file attached to an image.
	 * 
	 * @return sound path is String format
	 * @throws ImageIsEmptyException
	 * @throws SoundNotFoundException
	 */
	public String getSound() throws ImageIsEmptyException, SoundNotFoundException {
		if (isEmpty()) {
			throw new ImageIsEmptyException();
		}else if (mSound == null){
			throw new SoundNotFoundException();
		}
		
		return mSound;
	}
	
	private boolean exists(String uri) {
		// TODO This could be cached on first run, however this excludes situation where user deletes picture file on run
		File file = new File(uri);
		return file.exists();
	}
	
	/**
	 * Sets up an view to show the image, described by this object. 
	 * 
	 * @param view This view will be set to show the image.
	 */
	public void setImage(ImageView view) {
		if (!isEmpty()) {
			if (exists(mUri)) {
				view.setImageURI(Uri.parse(mUri));
			} else {
				view.setImageResource(R.drawable.na);
			}
		}
	}
	
	/**
	 * Describing whenever this picture is empty or not.
	 * 
	 * Empty pictures are used in the sentence board list, when a picture has
	 * not yet been dropped into a given position
	 *  
	 * @return True or False. 
	 */
	public boolean isEmpty() {
		return mEmpty;
	}
	
	/**
	 * Describing whether there is a sound attached to the image.
	 * 
	 * @return true or false
	 */
	public boolean hasSound() {
		return mSound != null ? true : false;
	}
	
	/**
	 * 
	 * \remark Update the entry within the database to reflect the change.
	 * 
	 * @throws ImageIsEmptyException If the image is empty.
	 */
	public void setUri(String uri) throws ImageIsEmptyException 
	{
		if (isEmpty()) {
			throw new ImageIsEmptyException();
		}
		
		mDB.open();
		mDB.setPicturePath(mId, uri);
		mDB.close();
		mUri = uri;
	}
	
	/**
	 * 
	 * \remark Update the entry within the database to reflect the change.
	 * 
	 * @param text
	 * @throws ImageIsEmptyException If the image is empty.
	 */
	public void setText(String text) throws ImageIsEmptyException
	{	
		if (isEmpty()) {
			throw new ImageIsEmptyException();
		}
		
		mDB.open(); 
		mDB.setPictureText(mId, text); 
		mDB.close();
		mText = text;
	}
	
	/**
	 * 
	 * \remark Update the entry within the database to reflect the change.
	 * 
	 * @param sound
	 * @throws ImageIsEmptyException If the image is empty.
	 */
	public void setSound(String sound) throws ImageIsEmptyException
	{	
		if (isEmpty()) {
			throw new ImageIsEmptyException();
		}
		
		mDB.open(); 
		mDB.setPictureSound(mId, sound); 
		mDB.close();
		mSound = sound;
	}
}
